# -*- coding: utf-8 -*-

from kivy.clock import Clock
from kivy.core.audio import SoundLoader
from kivy.properties import NumericProperty, StringProperty
from kivy.uix.boxlayout import BoxLayout

import model.gamestate
from constants import FAILED_SOUND, GUESSED_SOUND,\
    LAST_SECONDS_FINISHED_SOUND, PUT_BACK_SOUND, TIME_UP_SOUND
from model.gamestate import WordGuessResult
from ui.hat_widget import HatWidget

"""
It neeeds Gamestate with Settings.time_per_round_sec, Settings.time_left_sec
and Hat with methods Hat.add_word(), Hat.get_word()
It changes GameState.Game.game_round.current_word,
GameState.game_round.words
It can change phase from GUESS_WORD to RESULTS_OF_ONE_PAIR
It stores current word in gamestate.game_round.current_word
    if resulf isnt known
"""

DISABLE_TIME_SEC = 0.4
RELEASE_TIME = 2


class GuessWordScreen(HatWidget):
    pbValue = NumericProperty()
    pbMaxValue = NumericProperty()
    skip_words_left = NumericProperty()
    word_str = StringProperty()

    def __init__(self, gamestate, presenter, **kwargs):
        """
        It's constructor of GuessWordScreen
        Args:
            gamestate: (GameState)
            presenter: (Presenter)
        """
        super(GuessWordScreen, self).__init__(**kwargs)
        self.release_time = 0
        self.left_pressed = False
        self.right_pressed = False
        self.sound = SoundLoader.load(FAILED_SOUND)
        self.gamestate = gamestate
        self.presenter = presenter
        self.gamestate.game_round.words = []
        if not presenter.settings.game.may_pause_game:
            self.pause_button.enabled = False
        if not presenter.settings.game.is_progress_bar:
            """
            remove progressbar
            """
            self.remove_widget(self.progress_bar)

        self.get_word()
        self.is_last_second = False

        self.pbMaxValue = self.gamestate.settings.time_per_round_sec
        self.pbValue = self.pbMaxValue - \
            self.gamestate.game_round.time_left_sec

        if self.gamestate.game_round.time_left_sec > 0:
            Clock.schedule_interval(self.update_state, 0.02)
            self.is_time_out = False
        else:
            self.is_time_out = True
            self.word_label.color = 0.4, 0.4, 0.4, 1
            self.pause_button.enabled = False

        self.skip_words_left = self.presenter.settings.game.skip_words
        self.redraw_skip_button()
        Clock.schedule_interval(self.pick_sound, 2)

    def enable_guess_button(self, dt):
        self.guess_button.enabled = True

    def go_to_next(self):
        """
        It can change phase from GUESS_WORD to RESULTS_OF_ONE_PAIR
        """
        if not self.is_time_out:
            Clock.unschedule(self.update_state)
        Clock.unschedule(self.pick_sound)
        Clock.unschedule(self.enable_guess_button)
        Clock.unschedule(self.last_seconds_finished)
        self.presenter.change_phase(model.gamestate.Phase.RESULTS_OF_ONE_PAIR)

    def add_current_word(self, result):
        """
        It can add current word to GameState.game_round.words.
        Args:
            result: WordGuessResult
        """
        word = WordGuessResult(
            self.gamestate.game_round.current_word,
            result, self.gamestate.
            settings.time_per_round_sec
            - self.gamestate.game_round.time_left_sec)
        self.gamestate.game_round.words.append(word)

    def hat_is_empty(self):
        """
        This method checks that hat is empty
        """
        return len(self.gamestate.hat.words) == 0

    def get_word(self):
        """
        This method can get word from hat and draw it on the screen.
        It changes gamestate.game_round.current_word
        """
        if self.gamestate.game_round.current_word is None:
            self.gamestate.game_round.current_word =\
                self.gamestate.hat.next_word()
        self.word_str = self.gamestate.game_round.current_word.text

    def update_state(self, dt):
        self.pbValue += dt
        if self.gamestate.game_round is not None:
            self.gamestate.game_round.time_left_sec = self.pbMaxValue - \
                self.pbValue
        if ((self.pbValue >= self.pbMaxValue - 1) and
                (not self.is_last_second)):
            if (self.presenter.settings.sound.get_property('sound_on')):
                long_sound = SoundLoader.load(TIME_UP_SOUND)
                long_sound.play()
            self.is_last_second = True
        if ((self.pbValue >= self.pbMaxValue) and
                (not self.is_time_out)):
            self.presenter.adapter.vibrate()
            Clock.schedule_once(self.last_seconds_finished,
                                self.gamestate.settings.time_before_out_sec)
            self.pause_button.enabled = False
            self.skip_button.text = _('Not guessed')
            self.is_time_out = True
            self.word_label.color = 1, 0.4, 0.4, 1
            self.redraw_skip_button()
            Clock.unschedule(self.update_state)

    def pick_sound(self, dt):
        self.release_time += dt
        if self.release_time >= RELEASE_TIME and \
           not(self.left_pressed and self.right_pressed):
            self.sound.play()

    def button_released(self, pos):
        if self.left_pressed and self.right_pressed:
            self.release_time = 0
        if pos == 0:
            self.left_pressed = False
        else:
            self.right_pressed = False

    def button_pressed(self, pos):
        if self.left_pressed and self.right_pressed:
            self.release_time = 0
        if pos == 0:
            self.left_pressed = True
        else:
            self.right_pressed = True

    def last_seconds_finished(self, dt):
        if (self.presenter.settings.sound.get_property('sound_on')):
            long_sound = SoundLoader.load(LAST_SECONDS_FINISHED_SOUND)
            long_sound.play()
        self.presenter.adapter.vibrate()
        self.word_label.color = 0.4, 0.4, 0.4, 1
        self.redraw_skip_button()

    def hat_is_empty(self):
        """
        This method checks that hat is empty
        """
        return len(self.gamestate.hat.words) == 0

    def guessed(self):
        """
        This method add current word to curr_round.words, with GUESS flag.
        If Hat is not empty, then this word will be update_stated, else method
        GoToNext can change current game phase to RESULTS_OF_ONE_PAIR
        """
        if (self.presenter.settings.sound.get_property('sound_on')) and \
           (self.presenter.settings.sound.get_property('sound_guessed_on')):
            sound = SoundLoader.load(GUESSED_SOUND)
            sound.play()
        self.button_timer_stoped = True
        self.add_current_word(WordGuessResult.GUESS)
        self.gamestate.game_round.current_word = None
        if not (self.hat_is_empty() or self.is_time_out):
            self.guess_button.enabled = False
            Clock.schedule_once(self.enable_guess_button,
                                DISABLE_TIME_SEC)
            self.get_word()
        else:
            self.go_to_next()

    def fail(self):
        """
        This method add current word to curr_round.words, with FAIL flag and
        change game Phase to RESULTS_OF_ONE_PAIR game phase
        """
        if (self.presenter.settings.sound.get_property('sound_on')) and \
           (self.presenter.settings.sound.get_property('sound_failed_on')):
            sound = SoundLoader.load(FAILED_SOUND)
            sound.play()
        self.add_current_word(WordGuessResult.FAIL)
        self.gamestate.game_round.current_word = None
        self.go_to_next()

    def put_back(self):
        """
        This method add current word to curr_round.words, with PUT_BACK flag
        and add current word into the hat.
        """

        if (self.presenter.settings.sound.get_property('sound_on')) and \
           (self.presenter.settings.sound.get_property
                ('sound_put_back_on')):
            sound = SoundLoader.load(PUT_BACK_SOUND)
            sound.play()
        if self.is_time_out or self.skip_words_left <= 0:
            self.add_current_word(WordGuessResult.TIME_OUT)
            self.go_to_next()
        elif self.skip_words_left != 0:
            self.add_current_word(WordGuessResult.PUT_BACK)
            self.gamestate.hat.add_word(self.gamestate.game_round.current_word)
            self.gamestate.game_round.current_word = None
            self.get_word()

            if self.skip_words_left < 2:
                self.skip_words_left -= 1
                self.redraw_skip_button()

    def redraw_skip_button(self):
        if self.is_time_out:
            self.skip_button.text_normal = _('Not guessed')
            self.skip_button.is_normal_button = True
        elif self.skip_words_left > 0:
            self.skip_button.text_normal = _('Change')
            self.skip_button.is_normal_button = True
        else:
            self.skip_button.text_normal = _('End round')
            self.skip_button.is_normal_button = False

    def paused(self):
        if (not self.is_time_out):
            Clock.unschedule(self.update_state)
        Clock.unschedule(self.enable_guess_button)
        Clock.unschedule(self.last_seconds_finished)
        Clock.unschedule(self.pick_sound)
        self.presenter.change_phase(model.gamestate.Phase.FROM_TO)
